#pragma once
#include <box2d\Box2D.h>
#include "Singleton.h"


enum Box2DObjectType
{
	Object_Ground = 0,
	Object_Part,
};

struct BodyInfo
{
	uint uid;
	uint entity_type;
	b2BodyType  entity_bodytype;
	void* owner_point;

	BodyInfo()
	{
		uid = 0;
		entity_type = 0;
		owner_point = NULL;
		entity_bodytype = b2_staticBody;
	}

	BodyInfo(const BodyInfo& info)
	{
		entity_type = info.entity_type;
		owner_point = info.owner_point;
		entity_bodytype = info.entity_bodytype;
		uid =info.uid;
	}
};

class Box2DManager;
class b2BodySmart
{
	friend Box2DManager;
	b2Body* body;

	inline b2BodySmart& operator=(b2BodySmart& _Right);

	inline b2BodySmart(b2BodySmart& _Right);
public:

	inline b2Body& operator*() const 
	{
		return (*body);
	}

	inline b2Body* operator->() const
	{
		return body;
	}
	inline b2Body* Get() const
	{
		return body;
	}

	b2BodySmart():body(NULL)
	{

	}
	~b2BodySmart();
};

class Box2DManager :public Singleton<Box2DManager>
{
	friend Singleton;
private:
	// constructor.
	Box2DManager();

	// destructor.
	~Box2DManager();
public:
	// update
	void OnUpdate(float frameTime);

	// render
	void OnPreRender();

	void SetActiveWorld(bool flag);

	void SetEnableGravrity(bool flag);

	void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);

	void CreateBox(const BodyInfo& creator_info, b2BodySmart& sbody, const b2Transform& transform, const b2Vec2& size, float density = 1.f);

	void CretateCircle(const BodyInfo& creator_info, b2BodySmart& sbody, const b2Transform& transform, float radius, float density = 1.0f, float friction = 1.0f);

	void CreateJoint(const b2BodySmart& pA, const b2BodySmart& pB, b2RevoluteJointDef& jd);

	b2World* GetWorld();

	void SetContactListener(b2ContactListener* listener);

	bool IsEnableGravrity();



private:
	b2World* m_world;

	bool m_enableGravrity;
};